package cn.iocoder.yudao.module.ym.dal.mysql.site;

import java.time.LocalDate;
import java.util.*;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.ym.dal.dataobject.site.SiteDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.ym.controller.admin.site.vo.*;

/**
 * 电站 Mapper
 *
 * @author 韩艳阳
 */
@Mapper
public interface SiteMapper extends BaseMapperX<SiteDO> {

    default PageResult<SiteDO> selectPage(SitePageReqVO reqVO) {

        LambdaQueryWrapper<SiteDO> siteDOLambdaQueryWrapperX = new LambdaQueryWrapperX<SiteDO>()
                .inIfPresent(SiteDO::getId,reqVO.getIds())
                .likeIfPresent(SiteDO::getRemark, reqVO.getRemark())
                .betweenIfPresent(SiteDO::getCreateTime, reqVO.getCreateTime())
                .eqIfPresent(SiteDO::getAreaId, reqVO.getAreaId())
                .inIfPresent(SiteDO::getAreaId, reqVO.getAreaIdList())
                .likeIfPresent(SiteDO::getSiteName, reqVO.getSiteName())
                .likeIfPresent(SiteDO::getSiteCode, reqVO.getSiteCode())
                .eqIfPresent(SiteDO::getLocation, reqVO.getLocation())
                .eqIfPresent(SiteDO::getLatitudeLongitude, reqVO.getLatitudeLongitude())
                .eqIfPresent(SiteDO::getCoordinates, reqVO.getCoordinates())
                .inIfPresent(SiteDO::getOperationPlatform, reqVO.getOperationPlatformList())
                .inIfPresent(SiteDO::getDeviceBrand, reqVO.getDeviceBrandList())
                .eqIfPresent(SiteDO::getDeviceBrand, reqVO.getDeviceBrand())
                .inIfPresent(SiteDO::getDeviceType, reqVO.getDeviceTypeList())
                .eqIfPresent(SiteDO::getDeviceType, reqVO.getDeviceType())
                .eqIfPresent(SiteDO::getFastNum, reqVO.getFastNum())
                .eqIfPresent(SiteDO::getSlowNum, reqVO.getSlowNum())
                .likeIfPresent(SiteDO::getAdminName, reqVO.getAdminName())
                .eqIfPresent(SiteDO::getAdminPhone, reqVO.getAdminPhone())
                .eqIfPresent(SiteDO::getInspectionCount,reqVO.getInspectionCount())
                .inIfPresent(SiteDO::getSiteStatus, reqVO.getSiteStatusList())
                .eqIfPresent(SiteDO::getSiteStatus, reqVO.getSiteStatus())
                .inIfPresent(SiteDO::getOperationType, reqVO.getOperationTypeList())
                .eqIfPresent(SiteDO::getOperationType, reqVO.getOperationType())
                .eqIfPresent(SiteDO::getElectricityBill, reqVO.getElectricityBill())
                .eqIfPresent(SiteDO::getServiceFee, reqVO.getServiceFee())
                .betweenIfPresent(SiteDO::getOnlineDate, reqVO.getOnlineDate())
                .eqIfPresent(SiteDO::getInvestmentAmt, reqVO.getInvestmentAmt())
                .eqIfPresent(SiteDO::getTotalPower, reqVO.getTotalPower())
                .eqIfPresent(SiteDO::getShareRent, reqVO.getShareRent())
                .betweenIfPresent(SiteDO::getExpirationDate, reqVO.getExpirationDate())
                .likeIfPresent(SiteDO::getClientName, reqVO.getClientName())
                .likeIfPresent(SiteDO::getLeaderName, reqVO.getLeaderName())
                .eqIfPresent(SiteDO::getLeaderPhone, reqVO.getLeaderPhone())
                .eqIfPresent(SiteDO::getSiteTenure, reqVO.getSiteTenure())
                .eqIfPresent(SiteDO::getBusinessCategory, reqVO.getBusinessCategory())
                .eqIfPresent(SiteDO::getStationLoss, reqVO.getStationLoss())
                .eqIfPresent(SiteDO::getSiteIcon, reqVO.getSiteIcon())
                .eqIfPresent(SiteDO::getOperatingEnd, reqVO.getOperatingEnd())
                .betweenIfPresent(SiteDO::getInstallationTime, reqVO.getInstallationTime())
                .inIfPresent(SiteDO::getSiteType, reqVO.getSiteTypeList())
                .eqIfPresent(SiteDO::getSiteType, reqVO.getSiteType())
                .eqIfPresent(SiteDO::getCompany, reqVO.getCompany())
                .eqIfPresent(SiteDO::getExpansion, reqVO.getExpansion())
                .eqIfPresent(SiteDO::getExpansionDetail, reqVO.getExpansionDetail())
                .eqIfPresent(SiteDO::getExpansionProgress, reqVO.getExpansionProgress())
                .eqIfPresent(SiteDO::getStatus, reqVO.getStatus())
                .eqIfPresent(SiteDO::getInspectionCount, reqVO.getInspectionCount())
                .betweenIfPresent(SiteDO::getBusinessTime, reqVO.getBusinessTime())
                .last("ORDER BY CONVERT(site_name USING gbk)");

        //组合搜索
        String combinedSearch = reqVO.getCombinedSearch();
        if(combinedSearch != null && !combinedSearch.isEmpty()){
            siteDOLambdaQueryWrapperX.and(wrapper -> wrapper
                    .like(SiteDO::getLocation,combinedSearch) //电站地址
                    .or()
                    .like(SiteDO::getSiteName,combinedSearch) //电站名称
            );
        }

        //标签多选搜索
        String supportingFacilities = reqVO.getSupportingFacilities();
        if(supportingFacilities != null){
            String[] split = supportingFacilities.split(",");
            for (String s1 : split) {
                siteDOLambdaQueryWrapperX.apply("FIND_IN_SET("+s1+", supporting_facilities) > 0");
            }
        }
        // 处理经纬度距离过滤
        if (reqVO.getDis() != null && reqVO.getNowLon() != null && reqVO.getNowLat() != null) {
            Long dis = reqVO.getDis();
            Double nowLat = reqVO.getNowLat();
            Double nowLon = reqVO.getNowLon();

            // 1. 添加经纬度范围过滤（性能优化）
            double latRange = dis / 111000.0; // 纬度范围（1度≈111公里）
            double lonRange = dis / (111000.0 * Math.cos(Math.toRadians(nowLat))); // 经度范围
            siteDOLambdaQueryWrapperX.apply("lat BETWEEN {0} - {1} AND {0} + {1}", nowLat, latRange)
                    .apply("lon BETWEEN {0} - {1} AND {0} + {1}", nowLon, lonRange);

            // 2. 精确距离计算（Haversine公式）
            siteDOLambdaQueryWrapperX.apply("ROUND(" +
                    "6371 * 1000 * 2 * ASIN(" +
                    "SQRT(" +
                    "POW(SIN(RADIANS(lat - {0}) / 2), 2) + " +
                    "COS(RADIANS({0})) * COS(RADIANS(lat)) * " +
                    "POW(SIN(RADIANS(lon- {1}) / 2), 2)" +
                    ")" +
                    ")" +
                    ") <= {2}", nowLat, nowLon, dis);
        }
        Integer yearsLeft = reqVO.getYearsLeft();
        if (yearsLeft != null) {
            Integer currentYear = LocalDate.now().getYear();
            siteDOLambdaQueryWrapperX.apply("YEAR(expiration_date) - {0} = {1}", yearsLeft, currentYear);
        }
        //判断电站是否有电站照片
        String siteImages = reqVO.getSiteImages();
        //有图片的
        if (siteImages != null && siteImages.equals("1")) {
            //
            siteDOLambdaQueryWrapperX
                    .isNotNull(SiteDO::getSiteImages)
                    .ne(SiteDO::getSiteImages,"");
        }
        //没图片的
        else if (siteImages != null && siteImages.equals("0")) {

            siteDOLambdaQueryWrapperX
                    .isNull(SiteDO::getSiteImages)
                    .or()
                    .eq(SiteDO::getSiteImages,"");

        }
        return selectPage(reqVO, siteDOLambdaQueryWrapperX);
    }
    default List<SiteDO> selectList(SitePageReqVO reqVO) {
        LambdaQueryWrapper<SiteDO> siteDOLambdaQueryWrapperX = new LambdaQueryWrapperX<SiteDO>()
                .inIfPresent(SiteDO::getId,reqVO.getIds())
                .likeIfPresent(SiteDO::getRemark, reqVO.getRemark())
                .betweenIfPresent(SiteDO::getCreateTime, reqVO.getCreateTime())
                .eqIfPresent(SiteDO::getAreaId, reqVO.getAreaId())
                .inIfPresent(SiteDO::getAreaId, reqVO.getAreaIdList())
                .likeIfPresent(SiteDO::getSiteName, reqVO.getSiteName())
                .likeIfPresent(SiteDO::getSiteCode, reqVO.getSiteCode())
                .eqIfPresent(SiteDO::getLocation, reqVO.getLocation())
                .eqIfPresent(SiteDO::getLatitudeLongitude, reqVO.getLatitudeLongitude())
                .eqIfPresent(SiteDO::getCoordinates, reqVO.getCoordinates())
                .inIfPresent(SiteDO::getOperationPlatform, reqVO.getOperationPlatformList())
                .inIfPresent(SiteDO::getDeviceBrand, reqVO.getDeviceBrandList())
                .eqIfPresent(SiteDO::getDeviceBrand, reqVO.getDeviceBrand())
                .inIfPresent(SiteDO::getDeviceType, reqVO.getDeviceTypeList())
                .eqIfPresent(SiteDO::getDeviceType, reqVO.getDeviceType())
                .eqIfPresent(SiteDO::getFastNum, reqVO.getFastNum())
                .eqIfPresent(SiteDO::getSlowNum, reqVO.getSlowNum())
                .likeIfPresent(SiteDO::getAdminName, reqVO.getAdminName())
                .eqIfPresent(SiteDO::getAdminPhone, reqVO.getAdminPhone())
                .eqIfPresent(SiteDO::getInspectionCount,reqVO.getInspectionCount())
                .inIfPresent(SiteDO::getSiteStatus, reqVO.getSiteStatusList())
                .eqIfPresent(SiteDO::getSiteStatus, reqVO.getSiteStatus())
                .inIfPresent(SiteDO::getOperationType, reqVO.getOperationTypeList())
                .eqIfPresent(SiteDO::getOperationType, reqVO.getOperationType())
                .eqIfPresent(SiteDO::getElectricityBill, reqVO.getElectricityBill())
                .eqIfPresent(SiteDO::getServiceFee, reqVO.getServiceFee())
                .betweenIfPresent(SiteDO::getOnlineDate, reqVO.getOnlineDate())
                .eqIfPresent(SiteDO::getInvestmentAmt, reqVO.getInvestmentAmt())
                .eqIfPresent(SiteDO::getTotalPower, reqVO.getTotalPower())
                .eqIfPresent(SiteDO::getShareRent, reqVO.getShareRent())
                .betweenIfPresent(SiteDO::getExpirationDate, reqVO.getExpirationDate())
                .likeIfPresent(SiteDO::getClientName, reqVO.getClientName())
                .likeIfPresent(SiteDO::getLeaderName, reqVO.getLeaderName())
                .eqIfPresent(SiteDO::getLeaderPhone, reqVO.getLeaderPhone())
                .eqIfPresent(SiteDO::getSiteTenure, reqVO.getSiteTenure())
                .eqIfPresent(SiteDO::getBusinessCategory, reqVO.getBusinessCategory())
                .eqIfPresent(SiteDO::getStationLoss, reqVO.getStationLoss())
                .eqIfPresent(SiteDO::getSiteIcon, reqVO.getSiteIcon())
                .eqIfPresent(SiteDO::getOperatingEnd, reqVO.getOperatingEnd())
                .betweenIfPresent(SiteDO::getInstallationTime, reqVO.getInstallationTime())
                .inIfPresent(SiteDO::getSiteType, reqVO.getSiteTypeList())
                .eqIfPresent(SiteDO::getSiteType, reqVO.getSiteType())
                .eqIfPresent(SiteDO::getCompany, reqVO.getCompany())
                .eqIfPresent(SiteDO::getExpansion, reqVO.getExpansion())
                .eqIfPresent(SiteDO::getExpansionDetail, reqVO.getExpansionDetail())
                .eqIfPresent(SiteDO::getExpansionProgress, reqVO.getExpansionProgress())
                .eqIfPresent(SiteDO::getStatus, reqVO.getStatus())
                .eqIfPresent(SiteDO::getInspectionCount, reqVO.getInspectionCount())
                .betweenIfPresent(SiteDO::getBusinessTime, reqVO.getBusinessTime())
                .last("ORDER BY CONVERT(site_name USING gbk)");

        //组合搜索
        String combinedSearch = reqVO.getCombinedSearch();
        if(combinedSearch != null && !combinedSearch.isEmpty()){
            siteDOLambdaQueryWrapperX.and(wrapper -> wrapper
                    .like(SiteDO::getLocation,combinedSearch) //电站地址
                    .or()
                    .like(SiteDO::getSiteName,combinedSearch) //电站名称
            );
        }

        //标签多选搜索
        String supportingFacilities = reqVO.getSupportingFacilities();
        if(supportingFacilities != null){
            String[] split = supportingFacilities.split(",");
            for (String s1 : split) {
                siteDOLambdaQueryWrapperX.apply("FIND_IN_SET("+s1+", supporting_facilities) > 0");
            }
        }

        // 处理经纬度距离过滤
        if (reqVO.getDis() != null && reqVO.getNowLon() != null && reqVO.getNowLat() != null) {
            Long dis = reqVO.getDis();
            Double nowLat = reqVO.getNowLat();
            Double nowLon = reqVO.getNowLon();

            // 1. 添加经纬度范围过滤（性能优化）
            double latRange = dis / 111000.0; // 纬度范围（1度≈111公里）
            double lonRange = dis / (111000.0 * Math.cos(Math.toRadians(nowLat))); // 经度范围
            siteDOLambdaQueryWrapperX.apply("lat BETWEEN {0} - {1} AND {0} + {1}", nowLat, latRange)
                    .apply("lon BETWEEN {0} - {1} AND {0} + {1}", nowLon, lonRange);

            // 2. 精确距离计算（Haversine公式）
            siteDOLambdaQueryWrapperX.apply("ROUND(" +
                    "6371 * 1000 * 2 * ASIN(" +
                    "SQRT(" +
                    "POW(SIN(RADIANS(lat - {0}) / 2), 2) + " +
                    "COS(RADIANS({0})) * COS(RADIANS(lat)) * " +
                    "POW(SIN(RADIANS(lon- {1}) / 2), 2)" +
                    ")" +
                    ")" +
                    ") <= {2}", nowLat, nowLon, dis);
        }
        Integer yearsLeft = reqVO.getYearsLeft();
        if (yearsLeft != null) {
            Integer currentYear = LocalDate.now().getYear();
            siteDOLambdaQueryWrapperX.apply("YEAR(expiration_date) - {0} = {1}", yearsLeft, currentYear);
        }
        //判断电站是否有电站照片
        String siteImages = reqVO.getSiteImages();
        //有图片的
        if (siteImages != null && siteImages.equals("1")) {
            //
            siteDOLambdaQueryWrapperX
                    .isNotNull(SiteDO::getSiteImages)
                    .ne(SiteDO::getSiteImages,"");
        }
        //没图片的
        else if (siteImages != null && siteImages.equals("0")) {

            siteDOLambdaQueryWrapperX
                    .isNull(SiteDO::getSiteImages)
                    .or()
                    .eq(SiteDO::getSiteImages,"");

        }

        return selectList(siteDOLambdaQueryWrapperX);
    }

}
